package com.itcast.demo.completablefuture;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.CompletableFuture;

@RestController
@RequestMapping("/cf")
public class CompletableFutureBasic {

    @PostMapping("/test")
    public void test() {

        // 使用thenCombine合并两个异步任务的结果 thenCombine()方法会在两个异步任务都完成后，
        // 合并它们的结果。在这个例子中，我们将两个任务的结果相加，得到了合并后的结果30
//        test1();
        // 使用allOf (等待所有任务完成）和anyOf等待任意一个任务完成
        /**
         * allOf()方法会等待所有给定的CompletableFuture实例完成。如果其中任何一个任务失败，整个组合任务也会失败。•
         * 在所有任务完成后，thenRun()可以用于执行一些后续操作，比如打印“所有任务完成”。这种方法适合用于等待多个任务并发执行完毕的场景。
         * anyOf()方法会等待任意一个任务完成，并在完成时执行后续操作。• 在这个例子中，task2会更快完成，
         * 因此anyOfFuture会在task2完成时触发回调。这种方式适合用于只关心哪个任务先完成的场景，例如，多个备用任务中的一个先完成即满足条件。
         */
//        test2();
//        test3();

        // 异常处理与handle和exceptionally
        // exceptionally()方法用于捕捉异步任务中的异常，
        // 并返回一个默认值。在这个例子中，任务抛出异常后，我们返回了一个默认值-1，并输出异常信息
        /**
         * handle()方法不仅能处理异常，还可以处理正常结果。如果任务完成并没有抛出异常，它会返回正常的结果；
         * 如果抛出异常，它会返回一个默认值。通过handle()和exceptionally()，你可以灵活地应对异步任务中的异常
         */
//        test4();
//        test5();

        // 使用join与get获取结果,
        /**
         * CompletableFuture提供了join()和get()方法来获取异步任务的结果，
         * 它们的主要区别是异常处理方式。join()会在出现异常时抛出CompletionException
         * get()会在出现异常时抛出原始的异常类型。使用join()获取异步任务的结果，阻塞直到任务完成并返回结果
         */
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            return 10;
        });
        // 使用join()获取异步任务的结果
        Integer result = future.join();
        System.out.println("Result: " + result);
    }

    private static void test5() {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            if (true) {
                throw new RuntimeException("Some error occurred!");
            }
            return 10;
        });
        // 使用exceptionally()处理异常
        future.handle((result,ex)-> {
            if(ex != null) {
                System.out.println("Exception caught: " + ex.getMessage());
                return -1;
            }
           return result;
        }).thenAccept(result -> System.out.println("Result: " + result));
    }

    private static void test4() {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            if (true) {
                throw new RuntimeException("Some error occurred!");
            }
            return 10;
        });
        // 使用exceptionally()处理异常
        future.exceptionally((ex)-> {
            System.out.println("Exception caught: " + ex.getMessage());
            return -1;
        }).thenAccept(result -> System.out.println("Result: " + result));
    }

    private static void test3() {
        CompletableFuture<Void> task1 = CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(1000);
                System.out.println("Task 1 completed");
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        CompletableFuture<Void> task2 = CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(3000);
                System.out.println("Task 2 completed");
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        // 使用allOf等待所有任务完成
        CompletableFuture<Object> allTasks = CompletableFuture.anyOf(task1, task2);

        // 等待任意一个任务完成后执行
        allTasks.thenRun(() -> System.out.println("any of tasks completed"));

        allTasks.join(); // 阻塞当前线程，直到所有任务都执行完毕
    }

    private static void test2() {
        CompletableFuture<Void> task1 = CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(1000);
                System.out.println("Task 1 completed");
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        CompletableFuture<Void> task2 = CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(1000);
                System.out.println("Task 2 completed");
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        // 使用allOf等待所有任务完成
        CompletableFuture<Void> allTasks = CompletableFuture.allOf(task1, task2);

        // 等待所有任务完成后执行
        allTasks.thenRun(() -> System.out.println("All tasks completed"));

        allTasks.join(); // 阻塞当前线程，直到所有任务都执行完毕
    }

    private static void test1() {
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return 10;
        });

        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return 20;
        });
        // 合并两个异步任务的结果
        CompletableFuture<Integer> result = future1.thenCombine(future2, (x, y) -> x + y);
        System.out.println(result.join());
        // 使用thenAccept消费异步任务的结果
        result.thenAccept(x -> System.out.println("result: " + x));
    }
}
